#
# OpenCogGenPythonTypes.cmake
#
# Definitions for automatically building a Python `atom_types.pyx`
# file, given a master file `atom_types.script`.
#
# Example usage:
# OPENCOG_PYTHON_ATOMTYPES(atom_types.script core_types.pyx)
#
# ===================================================================

MACRO(OPENCOG_PYTHON_SETUP SCRIPT_FILE PYTHON_FILE)
	SET(PYTHON_SUPPORTED_VALUE_LIST)

	IF (NOT PYTHON_FILE)
		MESSAGE(FATAL_ERROR "OPENCOG_PYTHON_ATOMTYPES missing PYTHON_FILE")
	ENDIF (NOT PYTHON_FILE)

	MESSAGE(DEBUG "Generating Python Atom Type definitions from ${SCRIPT_FILE}.")

	FILE(WRITE "${PYTHON_FILE}"
		"\n"
		"# DO NOT EDIT THIS FILE! This file was automatically\n"
		"# generated from atom definitions in\n"
		"# ${SCRIPT_FILE}\n"
		"# by the macro OPENCOG_PYTHON_ATOMTYPES\n"
		"#\n"
		"# This file contains basic python wrappers for atom creation.\n"
		"#\n"
		"\n"
	)
ENDMACRO()

# ------------
# Print out the python definitions. Note: We special-case Atom
# since we don't want to create a function with the same
# identifier as the Python Atom object.
MACRO(OPENCOG_PYTHON_WRITE_DEFS PYTHON_FILE)
	IF (NOT TYPE_NAME STREQUAL "Atom")

		# XXX This is broken in two ways. First, createValue() is
		# a C++ template, and so it can't be used like this.
		# Also, PYTHON_SUPPORTED_VALUE_LIST is an empty list (above)
		# so this is a no-op, anyway. XXX FIXME someday, I guess
		# Until then, the value ctors are hard-coded into
		# opencog/cython/opencog/type_constructors.pyx
		IF (ISVALUE STREQUAL "VALUE" OR ISSTREAM STREQUAL "STREAM")
			LIST(FIND PYTHON_SUPPORTED_VALUE_LIST ${TYPE_NAME} _INDEX)
			IF (${_INDEX} GREATER -1)
				# Single arg will work as all of the value constructors
				# have a single argument: either a value or a vector.
				FILE(APPEND "${PYTHON_FILE}"
					"def ${TYPE_NAME}(arg):\n"
					"    return createValue(types.${TYPE_NAME}, arg)\n"
				)
			ENDIF (${_INDEX} GREATER -1)
		ENDIF (ISVALUE STREQUAL "VALUE" OR ISSTREAM STREQUAL "STREAM")

		IF (ISNODE STREQUAL "NODE")
			FILE(APPEND "${PYTHON_FILE}"
				"def ${TYPE_NAME}(node_name):\n"
				"    return add_node(types.${TYPE_NAME}, node_name)\n"
			)
			IF (NOT SHORT_NAME STREQUAL "")
				FILE(APPEND "${PYTHON_FILE}"
					"def ${SHORT_NAME}(node_name):\n"
					"    return add_node(types.${TYPE_NAME}, node_name)\n"
				)
			ENDIF (NOT SHORT_NAME STREQUAL "")
		ENDIF (ISNODE STREQUAL "NODE")

		IF (ISLINK STREQUAL "LINK")
			FILE(APPEND "${PYTHON_FILE}"
				"def ${TYPE_NAME}(*args):\n"
				"    return add_link(types.${TYPE_NAME}, args)\n"
			)
			IF (NOT SHORT_NAME STREQUAL "")
				FILE(APPEND "${PYTHON_FILE}"
					"def ${SHORT_NAME}(*args):\n"
					"    return add_link(types.${TYPE_NAME}, args)\n"
				)
			ENDIF (NOT SHORT_NAME STREQUAL "")
		ENDIF (ISLINK STREQUAL "LINK")
	ENDIF (NOT TYPE_NAME STREQUAL "Atom")

	# If not named as a node or a link, assume its a link
	# This is kind of hacky, but I don't know what else to do ...
	IF (NOT ISATOMSPACE STREQUAL "ATOM_SPACE" AND
		NOT ISNODE STREQUAL "NODE" AND
		NOT ISLINK STREQUAL "LINK" AND
		NOT ISVALUE STREQUAL "VALUE" AND
		NOT ISSTREAM STREQUAL "STREAM")
		FILE(APPEND "${PYTHON_FILE}"
			"def ${TYPE_NAME}(*args):\n"
			"    return add_link(types.${TYPE_NAME}, args)\n"
		)
	ENDIF (NOT ISATOMSPACE STREQUAL "ATOM_SPACE" AND
		NOT ISNODE STREQUAL "NODE" AND
		NOT ISLINK STREQUAL "LINK" AND
		NOT ISVALUE STREQUAL "VALUE" AND
		NOT ISSTREAM STREQUAL "STREAM")
ENDMACRO(OPENCOG_PYTHON_WRITE_DEFS PYTHON_FILE)

# ------------
# Main entry point.
MACRO(OPENCOG_PYTHON_ATOMTYPES SCRIPT_FILE PYTHON_FILE)

	OPENCOG_PYTHON_SETUP(${SCRIPT_FILE} ${PYTHON_FILE})
	FILE(STRINGS "${SCRIPT_FILE}" TYPE_SCRIPT_CONTENTS)
	FOREACH (LINE ${TYPE_SCRIPT_CONTENTS})
		OPENCOG_TYPEINFO_REGEX()
		IF (MATCHED AND CMAKE_MATCH_1)

			OPENCOG_TYPEINFO_SETUP()
			OPENCOG_PYTHON_WRITE_DEFS(${PYTHON_FILE})  # Print out python definitions
		ELSEIF (NOT MATCHED)
			MESSAGE(FATAL_ERROR "Invalid line in ${SCRIPT_FILE} file: [${LINE}]")
		ENDIF ()
	ENDFOREACH (LINE)

ENDMACRO()

#####################################################################
